home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / System 7.0 Samples / AEObject-Edition1.0.2 Sample / AEUtilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-18  |  23.2 KB  |  633 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. *
  3. *  Apple Developer Technical Support
  4. *
  5. *  AppleEvent utility routines
  6. *
  7. *  Program:AEObject-Edition Sample
  8. *  File:   AEUtilityRoutines.c - C Source
  9. *
  10. *  by: C.K. Haun <TR>
  11. *
  12. *  Copyright © 1991-1992 Apple Computer, Inc.
  13. *  All rights reserved.
  14. *
  15. *------------------------------------------------------------------------------
  16. * This file contains some generic and specific utility routines I wrote
  17. * to help with the AppleEvent manager.  The prime motivation for this file
  18. * is to NOT have to type in all the fields needed for many of the
  19. * AEM parameter accessing routines, since I do them so often.  
  20. * There aren't all that many calls here yet, this will grow as the AEM world grows
  21. *----------------------------------------------------------------------------*/
  22.  
  23.  
  24. #define __AEMU__
  25.  
  26. #include "Sampdefines.h"
  27.  
  28. #pragma segment AEUtils
  29. /* A little routine that returns a short from a descriptor */
  30. OSErr ShortFromDesc(short *theData, const AppleEvent *theDesc)
  31. {
  32.     OSErr myErr = noErr;
  33.     AEDesc tempDesc;
  34.     long temp;
  35.     if (theDesc->descriptorType == typeShortInteger) {
  36.         
  37.         temp = *((short *)*(theDesc->dataHandle));
  38.         *theData = temp;
  39.     } else {
  40.     /* if it wasn't a short to begin with, try and coerce it into a short */
  41.         myErr = AECoerceDesc(theDesc, typeShortInteger, &tempDesc);
  42.         if (!myErr) {
  43.             /* it coerced.  grab it */
  44.             temp = *((short *)*(tempDesc.dataHandle));
  45.             *theData = temp;
  46.             AEDisposeDesc(&tempDesc);
  47.         }
  48.     }
  49.     return(myErr);
  50.     
  51. }
  52. /* this has been replaced by my coercion handler, see AppleEventCore.c  */
  53. void PStringFromTextDesc(Str255 theString, const AEDesc *theDesc)
  54. {
  55.     theString[0] = GetHandleSize(theDesc->dataHandle);
  56.     BlockMove((Ptr)*theDesc->dataHandle, (Ptr)&theString[1], theString[0]);
  57.     
  58. }
  59.  
  60. /* Puts up the PPCBrowser, and creates a target address */
  61. /* based on the user selection */
  62. OSErr BrowseForTarget(AEDesc *theAddress)
  63. {
  64.     Str32 prompt1;
  65.     Str32 prompt2;
  66.     LocationNameRec theLoc;
  67.     PortInfoRec theRec;
  68.     OSErr myErr = noErr;
  69.     TargetID theID;
  70.     GetIndString(prompt1,kGeneralStrings,kPPCPrompt1);
  71.     GetIndString(prompt2,kGeneralStrings,kPPCPrompt2);
  72.     myErr = PPCBrowser(prompt1, prompt2, false, &theLoc, &theRec, nil, nil);
  73.     if (!myErr) {
  74.         /* make a target descriptor */
  75.         BlockMove(theRec.name.name, targetName, theRec.name.name[0] + 1);
  76.         ParamText(&targetName, "", "", "");
  77.         theID.name = theRec.name;
  78.         theID.location = theLoc;
  79.         myErr = AECreateDesc(typeTargetID, (Ptr)&theID, sizeof(theID), theAddress);
  80.         
  81.     }
  82.     mAEErrorDisplay("\pBrowser Error", myErr)
  83.     return(myErr);
  84. }
  85.  
  86. /* Makes an AppleEvent address descriptor based on the settings in the Dialog Box */
  87. /* in AppleEventCore.c */
  88. OSErr MakeAddress(AEDesc *theAddress)
  89. {
  90.     OSErr myErr = noErr;
  91.     ProcessSerialNumber myNumber;
  92.     switch (gAddressMode) {
  93.     /* Remember, if you use this case (using the PSN of kCurrentProcess) the  */
  94.     /* AppleEvent Manager will bypass the event loop and directly call (like a normal */
  95.     /* subroutine call) your handler, the event will _not_ come through */
  96.     /* WaitNextEvent */
  97.         case kSelfCur:
  98.             myNumber.highLongOfPSN = 0;
  99.             myNumber.lowLongOfPSN = kCurrentProcess;
  100.             myErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&myNumber, sizeof(ProcessSerialNumber), theAddress);
  101.             break;
  102.     /* If you use your real PSN, then the event will come through WNE */        
  103.         case kSelfPSN:
  104.             myErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&gOurSN, sizeof(ProcessSerialNumber), theAddress);
  105.             break;
  106.         case kOtherApp:
  107.             if (gTargetAddress.dataHandle == nil) {
  108.                 myErr = BrowseForTarget(theAddress);
  109.             } else {
  110.             /* If I already have one, duplicate it and pass it back */
  111.                 myErr = AEDuplicateDesc(&gTargetAddress, theAddress);
  112.             }
  113.             break;
  114.     }
  115.     mAEErrorDisplay("\pMakeAddress ", myErr)
  116.     return(myErr);
  117. }
  118.  
  119. /* generic sender, so I don't have to duplicate the various conditional code */
  120. /* (for replies, interactions, or whatever) all over */
  121. OSErr DoSend(AppleEvent *theEvent, AEDesc *reply)
  122. {
  123.     AEDesc *replyPointer = nil;
  124.     short response = 2;
  125.     OSErr myErr;
  126.     long timeOut = kAEDefaultTimeout;
  127.     if (gReplyMode)
  128.         replyPointer = reply;
  129.     if (gReplyMode == 1 && gAddressMode == 1) {
  130.         ModalFilterUPP upp = NewModalFilterProc(standardAlertFilter);
  131.         timeOut = 0;
  132.         response = CautionAlert(kBadMix, upp);
  133.         DisposeRoutineDescriptor(upp);
  134.     }
  135.     if (response == 2) {
  136.         myErr = AESend(theEvent, replyPointer,
  137.                        (gSendInteractArray[gAESendInteraction] + gAESwitchLayer) + gReplyLevels[gReplyMode], kAENormalPriority,
  138.                        timeOut, gCommonIdleFunctionUPP, nil);
  139.         
  140.         mAEErrorDisplay("\pAESend in DoSend ", myErr)
  141.     } else {
  142.         myErr = userCanceledErr;
  143.     }
  144.     return(myErr);
  145. }
  146.  
  147. /* lil routine that will print out actual error text for AEM errors, since I */
  148. /* got real tired of trying to remeber what -1723 was. */
  149. /* revised to reflect the new error codes, and to use my ERST <ckh 1.0.2>*/
  150. /* resource <ckh 1.0.2>*/
  151. void AEErrorText(OSErr theError)
  152. {
  153.     Str63 theWords;
  154.     Ptr theErrors;
  155.     OSErr tempError;
  156.     register qq;
  157.     short errCount;
  158.     Byte stringLen;
  159.     /* get my errors <ckh 1.0.2>*/
  160.     Handle scratch = GetResource(kErrorStringResourceType,kTheErrorStrings);
  161.     theWords[0] = 0;
  162.     if(scratch){
  163.         /* if I got it, lock it and deref <ckh 1.0.2>*/
  164.         HLock(scratch);
  165.         theErrors = *scratch;
  166.         errCount =  *((short *)theErrors);
  167.         /* position to the first error code <ckh 1.0.2>*/
  168.         theErrors = theErrors+sizeof(short);
  169.         errCount--;
  170.         for(qq = 0;qq<errCount;qq++){
  171.             tempError =  *((short *)theErrors);
  172.             theErrors = theErrors + sizeof (OSErr);
  173.             /* get the string count, we'll need this whatever we do <ckh 1.0.2>*/
  174.             stringLen = *theErrors;
  175.             stringLen ++;    
  176.             if(tempError == theError){
  177.                 /* it's this one, theErrors points to the string <ckh 1.0.2>*/
  178.                 BlockMove(theErrors,(Ptr)&theWords,stringLen);
  179.                 break;
  180.                 
  181.                 } else {
  182.                 /* next errror please <ckh 1.0.2>*/
  183.                 theErrors = theErrors + stringLen;
  184.                 }
  185.             }
  186.         if(theWords[0] == 0){
  187.             GetIndString(theWords,kGeneralStrings,kUnknownError);
  188.             }    
  189.         AddAEText(theWords);
  190.         HUnlock(scratch);
  191.         ReleaseResource(scratch);
  192.         }
  193. }
  194.  
  195. /* this just pumps out the returned data to the AEWindow */
  196. /* just a utility for this sample */
  197. void DisplayReturnedData(AEDesc *reply)
  198. {
  199.     AEDesc theData;
  200.     OSErr myErr;
  201.     long errorCode = 0;
  202.     DescType returnedType;
  203.     Size returnedSize;
  204.     Str255 returnedText;
  205.     /* I can do most of this by asking for typeChar and getting the desc. */
  206.     /* this is because the AEM can coerce any numeric data to typeChar */
  207.     /* (as described in the AEM chapter of IM VI) */
  208.     /* For things that the AEM _doesn't_ know about, I will install */
  209.     /* coercion handlers! */
  210.     /* if the coercion completely fails, because I got something I no nothing about, I bail */
  211.     mVerboseOutput("\p\n Returned Data was : ")
  212.     myErr = AEGetParamDesc(reply, keyDirectObject, typeChar, &theData);
  213.     if (!myErr) {
  214.         long size = GetHandleSize(theData.dataHandle);
  215.         HLock(theData.dataHandle);
  216.         
  217.         AddToAEWindow((Ptr)*(theData.dataHandle), size);
  218.         
  219.     } else {
  220.         /* get it as a wildcard, and just show me the descType */
  221.         myErr = AEGetParamDesc(reply, keyDirectObject, typeWildCard, &theData);
  222.         AddToAEWindow((Ptr)&theData.descriptorType, kFour);
  223.     }
  224.     /* I got a desc, I need to dispose a desc */
  225.     if (!myErr)
  226.         AEDisposeDesc(&theData);
  227.     else
  228.         AddAEText("\p not available");
  229.     /* see if there was an 'errs' or 'errn' added */
  230.     myErr = AEGetParamPtr(reply, keyErrorNumber, typeLongInteger, &returnedType, (Ptr)&errorCode, sizeof(long), &returnedSize);
  231.     if (myErr && myErr != errAEDescNotFound) {
  232.         
  233.         mVerboseOutput("\p\n Had an error descriptor, but I can't access it")
  234.     }
  235.     if (!myErr) {
  236.         mVerboseOutput("\p\n Error number (errn) returned, was: ")
  237.         AddAENum(errorCode);
  238.         AEErrorText(errorCode);
  239.     }
  240.     /* try for the error string */
  241.     myErr = AEGetParamPtr(reply, keyErrorString, typeMyPString, &returnedType, (Ptr)&returnedText, 255, &returnedSize);
  242.     if (!myErr) {
  243.         mVerboseOutput("\p\n Error string (errs) returned, was: ")
  244.         AddAEText(&returnedText);
  245.     }
  246. }
  247.  
  248.  
  249. /* DoObjectDefinition drives the dialog that sets up the default containers */
  250. /* for this sample, boring dialog stuff */
  251. void DoObjectDefinition(short which)
  252. {
  253.     DialogPtr tdial;
  254.     short hitItem = 0;
  255.     Boolean r5, r6;
  256.     Str32 tempNum;
  257.     register qq;
  258.     long realNum;
  259.     DescType shapeTypes[] =  {
  260.        cGraphicLine, cRectangle, cOval
  261.     };
  262.     tdial = SetUpObjectDialog(which);
  263.     ShowWindow(tdial);
  264.     
  265.     {
  266.         ModalFilterUPP upp = NewModalFilterProc(standardDialogFilter);
  267.  
  268.         while (hitItem != ok && hitItem != cancel) {
  269.             ModalDialog(upp, &hitItem);
  270.             switch (which) {
  271.                 case kSetWindowObject:
  272.                     switch (hitItem) {
  273.                         case kWByIndex:
  274.                         case kWByName:
  275.                             if (hitItem == kWByIndex) {
  276.                                 r5 = true;
  277.                                 r6 = false;
  278.                             } else {
  279.                                 r5 = false;
  280.                                 r6 = true;
  281.                             }
  282.                             SetControlValue(SnatchHandle(tdial, kWByIndex), r5);
  283.                             SetControlValue(SnatchHandle(tdial, kWByName), r6);
  284.                             
  285.                             break;
  286.                     }
  287.                     break;
  288.                 case kSetTextObject:
  289.                     switch (hitItem) {
  290.                         case kWordIndex:                        /* checkbox only to worry about */
  291.                             SetControlValue(SnatchHandle(tdial, kWordIndex), (GetControlValue(SnatchHandle(tdial, kWordIndex)) ? 0 : 1));
  292.                     }
  293.                     break;
  294.                 case kSetShapeObject:
  295.                     switch (hitItem) {
  296.                         case kLineRadio:
  297.                         case kRectangleRadio:
  298.                         case kOvalRadio:
  299.                             /* find out which one is true */
  300.                             for (qq = kLineRadio; qq < kOvalRadio + 1; qq++) {
  301.                                 if (GetControlValue(SnatchHandle(tdial, qq))) {
  302.                                     if (!(qq == hitItem)) {
  303.                                         SetControlValue(SnatchHandle(tdial, qq), false);
  304.                                         SetControlValue(SnatchHandle(tdial, hitItem), true);
  305.                                     }
  306.                                 }
  307.                             }
  308.                             break;
  309.                     }
  310.                     break;
  311.             }
  312.         }
  313.         DisposeRoutineDescriptor(upp);
  314.     }
  315.     /* make the changes permenent */
  316.     if (hitItem == ok) {
  317.         gPreferences.prefsChanged = true;
  318.         switch (which) {
  319.             case kSetWindowObject:
  320.                 HLock((Handle)gWindObjSpecHandle);
  321.                 if (GetControlValue(SnatchHandle(tdial, kWByIndex))) {
  322.                     /* going by absolute position */
  323.                     (*gWindObjSpecHandle)->form = formAbsolutePosition;
  324.                     GetDialogItemText((Handle)SnatchHandle(tdial, kWIndexNum), tempNum);
  325.                     StringToNum(tempNum, &realNum);
  326.                     (*gWindObjSpecHandle)->u.index = realNum;
  327.                 } else {
  328.                     /* going by name */
  329.                     (*gWindObjSpecHandle)->form = formName;
  330.                     /* put the name where it belongs */
  331.                     GetDialogItemText((Handle)SnatchHandle(tdial, kWIndexName), (*gWindObjSpecHandle)->u.name);
  332.                     
  333.                 }
  334.                 HUnlock((Handle)gWindObjSpecHandle);
  335.                 break;
  336.             case kSetTextObject:
  337.                 
  338.                 HLock((Handle)gTextObjSpecHandle);
  339.                 /* fewer choices here */
  340.                 GetDialogItemText((Handle)SnatchHandle(tdial, kTextONumber), tempNum);
  341.                 
  342.                 StringToNum(tempNum, &realNum);
  343.                 (*gTextObjSpecHandle)->u.index = realNum;
  344.                 (*gTextObjSpecHandle)->andWord = GetControlValue(SnatchHandle(tdial, kWordIndex));
  345.                 /* see if word is being asked for */
  346.                 if ((*gTextObjSpecHandle)->andWord) {
  347.                     GetDialogItemText((Handle)SnatchHandle(tdial, kWordIndexString), tempNum);
  348.                     StringToNum(tempNum, &realNum);
  349.                     (*gTextObjSpecHandle)->wordNumber = realNum;
  350.                     
  351.                 }
  352.                 HUnlock((Handle)gTextObjSpecHandle);
  353.                 break;
  354.             case kSetShapeObject:
  355.                 HLock((Handle)gShapeObjSpecHandle);
  356.                 for (qq = kLineRadio; qq < kOvalRadio + 1; qq++) {
  357.                     if (GetControlValue(SnatchHandle(tdial, qq))) {
  358.                         (*gShapeObjSpecHandle)->type = qq - kLineRadio;
  359.                         (*gShapeObjSpecHandle)->form = shapeTypes[qq - kLineRadio];
  360.                         break;
  361.                     }
  362.                 }
  363.                 /* and the index number */
  364.                 GetDialogItemText((Handle)SnatchHandle(tdial, kSIEditLine), tempNum);
  365.                 StringToNum(tempNum, &realNum);
  366.                 (*gShapeObjSpecHandle)->u.index = realNum;
  367.                 HUnlock((Handle)gShapeObjSpecHandle);
  368.                 break;
  369.         }
  370.     }
  371.     DisposeDialog(tdial);
  372. }
  373.  
  374. /* Anther case of not wanting to type dialog code all over the sample */
  375. DialogPtr SetUpObjectDialog(short which)
  376. {
  377.     DialogPtr tdial = CommonDStart(which, nil, nil);
  378.     short tempItem;
  379.     Str63 tempString;
  380.     switch (which) {
  381.         
  382.         case kSetWindowObject:
  383.             HLock((Handle)gWindObjSpecHandle);
  384.             if ((*gWindObjSpecHandle)->form == 0) {
  385.                 tempItem = kWPosRadio;                               /* default for the first time the app is run */
  386.             } else {
  387.                 
  388.                 if ((*gWindObjSpecHandle)->form == formAbsolutePosition) {
  389.                     
  390.                     tempItem = kWPosRadio;
  391.                     NumToString((*gWindObjSpecHandle)->u.index, tempString);
  392.                     SetDialogItemText((Handle)SnatchHandle(tdial, kWPosNum), tempString);
  393.                 } else {
  394.                     tempItem = kWTitleRadioSet;
  395.                     SetDialogItemText((Handle)SnatchHandle(tdial, kWTitleELine), (*gWindObjSpecHandle)->u.name);
  396.                 }
  397.             }
  398.             SetControlValue(SnatchHandle(tdial, tempItem), true);
  399.             HUnlock((Handle)gWindObjSpecHandle);
  400.             break;
  401.         case kSetTextObject:
  402.             HLock((Handle)gTextObjSpecHandle);
  403.             /* fewer choices here */
  404.             NumToString((*gTextObjSpecHandle)->u.index, tempString);
  405.             SetDialogItemText((Handle)SnatchHandle(tdial, kWPosRadio), tempString);
  406.             /* see if word is being asked for */
  407.             if ((*gTextObjSpecHandle)->andWord) {
  408.                 SetControlValue(SnatchHandle(tdial, kWTitleRadioSet), true);
  409.                 NumToString((*gTextObjSpecHandle)->wordNumber, tempString);
  410.                 SetDialogItemText((Handle)SnatchHandle(tdial, kWPosNum), tempString);
  411.                 
  412.             }
  413.             HUnlock((Handle)gTextObjSpecHandle);
  414.             break;
  415.         case kSetShapeObject:
  416.             HLock((Handle)gShapeObjSpecHandle);
  417.             if (!(*gShapeObjSpecHandle)->u.index)
  418.                 (*gShapeObjSpecHandle)->u.index = 1;
  419.             NumToString((*gShapeObjSpecHandle)->u.index, tempString);
  420.             SetDialogItemText((Handle)SnatchHandle(tdial, kSIEditLine), tempString);
  421.             SetControlValue(SnatchHandle(tdial, ((*gShapeObjSpecHandle)->type) + kLineRadio), true);
  422.             /* byIndex defaults to on for now */
  423.             SetControlValue(SnatchHandle(tdial, kSByIndexRadio), true);
  424.             
  425.             break;
  426.         default:
  427.             break;
  428.     }
  429.     return(tdial);
  430. }
  431.  
  432.  
  433.  
  434.  
  435.  
  436. /* this is a central point to add keyErrorText and keyErrorNumber  */
  437. /* parameters to a reply */
  438. /* just a handy thing to do. */
  439. /* It first checks to see if an error is already recorded, if there is one */
  440. /* (for an earlier stage in the process) they we exit, since the user will have to */
  441. /* deal with the ealier problem before they tackle the one we've just been called  */
  442. /* to add */
  443. /* •••• BE SURE that you null out the gCurrentReply (or whatever you use) pointer */
  444. /* when you exit from your handler, or you could end up writing to a desc that isn't  */
  445. /* there.  And of course, if you send events to yourself from within a handler */
  446. /* you're going to have to use a differrent method than this.  It's a sample, see? */
  447. void AddToReply(ConstStr255Param theWords, long theError)
  448. {
  449.     OSErr myErr = noErr;
  450.     long errNo;
  451.     DescType returnedType;
  452.     Size returnedSize;
  453.     
  454.     /* First, is therre a reply hanging out? */
  455.     if (gCurrentReply) {
  456.         /* test to see if there is one already*/
  457.         myErr = AEGetParamPtr(gCurrentReply, keyErrorNumber, typeLongInteger, &returnedType, (Ptr)&errNo, sizeof(long),
  458.                               &returnedSize);
  459.         
  460.         if (myErr == errAEDescNotFound) {
  461.             /* cool, press on.  */
  462.             myErr = AEPutParamPtr(gCurrentReply, keyErrorNumber, typeLongInteger, (Ptr)&theError, sizeof(long));
  463.             if (!myErr)
  464.                 myErr = AEPutParamPtr(gCurrentReply, keyErrorString, typeChar, (Ptr)&theWords[1], theWords[0]);
  465.             
  466.         }
  467.     }
  468. }
  469.  
  470. OSErr MakeTypeRect(CShapeObjHandle theShape, AEDesc *theValue)
  471. {
  472.     OSErr myErr = noErr;
  473.     AEDesc pixDesc;
  474.     AEDescList theList;
  475.     RGBColor black =  {
  476.         0, 0, 0
  477.     };
  478.     RGBColor white =  {
  479.         0xffff, 0xffff, 0xffff
  480.     };
  481.     short penSize = 1;
  482.     long copyWord = kAEQDCopy;
  483.     ShapesHandle theRealShape = (*theShape)->theShape;
  484.     HLock((Handle)theRealShape);
  485.     /* Now, a typeRectangle is a bunch of stuff, and as the AE Registry so clearly says... */
  486.     /* "Note that the Apple Event Manager can coerce any Apple event record into any 
  487.     other descriptor type. A special coercion handler is not required."
  488.     */
  489.     /* If you always wondered what that meant (I know I did) then watch */
  490.     /* create a list that is a record */
  491.     myErr = AECreateList(nil, nil, true, &theList);
  492.     /* now start adding all the junk I have lying around, rectangle, color, kitchen sink.... */
  493.     if (!myErr)
  494.         myErr = MakeSinglePixelMap(&pixDesc, &(*theRealShape)->theColor);
  495.     /* jeeez don't try and write code while the Finder is doing a copy across LocalTalk in the background Like I'm trying to now.... */
  496.     if (!myErr)
  497.         myErr = AEPutParamDesc(&theList, keyAEPenPattern, &pixDesc);
  498.     if (!myErr)
  499.         myErr = AEPutParamDesc(&theList, keyAEFillPattern, &pixDesc);
  500.     AEDisposeDesc(&pixDesc);
  501.     if (!myErr)
  502.         myErr = MakeSinglePixelMap(&pixDesc, &white);
  503.     if (!myErr)
  504.         myErr = AEPutParamDesc(&theList, keyAEFillColor, &pixDesc);
  505.     AEDisposeDesc(&pixDesc);
  506.     if (!myErr)
  507.         myErr = AEPutParamPtr(&theList, keyAEPenWidth, typeShortInteger, (Ptr)&penSize, sizeof(short));
  508.     if (!myErr)
  509.         myErr = AEPutParamPtr(&theList, keyAETransferMode, typeEnumeration, (Ptr)©Word, sizeof(long));
  510.     
  511.     if (!myErr)
  512.         myErr = AEPutParamPtr(&theList, keyAEBounds, typeQDRectangle, (Ptr)&(*theRealShape)->theRect, sizeof(Rect));
  513.     if (!myErr)
  514.         myErr = AEPutParamPtr(&theList, keyAEDefinitionRect, typeQDRectangle, (Ptr)&(*theRealShape)->theRect, sizeof(Rect));
  515.     HUnlock((Handle)theRealShape);
  516.     /* and coerce it into what we want */
  517.     if (!myErr)
  518.         myErr = AECoerceDesc(&theList, typeRectangle, theValue);
  519.     AEDisposeDesc(&theList);
  520.     mAEErrorDisplay("\p\n Error creating typeRectangle", myErr)
  521.     return(myErr);
  522. }
  523.  
  524. /* MakeGraphicLine is similar to making a typeRectangle */
  525.  
  526. OSErr MakeGraphicLine(CShapeObjHandle theShape, AEDesc *theValue)
  527. {
  528.     OSErr myErr = noErr;
  529.     AEDesc emptyList;
  530.     AEDesc pixDesc;
  531.     AEDescList theList;
  532.     RGBColor black =  {
  533.         0, 0, 0
  534.     };
  535.     RGBColor white =  {
  536.         0xffff, 0xffff, 0xffff
  537.     };
  538.     short penSize = 1;
  539.     long copyWord = kAEQDCopy;
  540.     DescType noArr = kAENoArrow;
  541.     ShapesHandle theRealShape = (*theShape)->theShape;
  542.     HLock((Handle)theRealShape);
  543.     myErr = AECreateList(nil, nil, true, &theList);
  544.     /* now start adding all the junk I have lying around, rectangle, color, kitchen sink.... */
  545.     if (!myErr)
  546.         myErr = MakeSinglePixelMap(&pixDesc, &(*theRealShape)->theColor);
  547.     /* jeeez don't try and write code while the Finder is doing a copy across LocalTalk in the background Like I'm trying to now.... */
  548.     if (!myErr)
  549.         myErr = AEPutParamDesc(&theList, keyAEPenPattern, &pixDesc);
  550.     if (!myErr)
  551.         myErr = AEPutParamDesc(&theList, keyAEPenColor, &pixDesc);
  552.     AEDisposeDesc(&pixDesc);
  553.     if (!myErr)
  554.         myErr = AEPutParamPtr(&theList, keyAEPenWidth, typeShortInteger, (Ptr)&penSize, sizeof(short));
  555.     if (!myErr)
  556.         myErr = AEPutParamPtr(&theList, keyAETransferMode, typeEnumeration, (Ptr)©Word, sizeof(long));
  557.     
  558.     if (!myErr)
  559.         myErr = AEPutParamPtr(&theList, keyAEBounds, typeQDRectangle, (Ptr)&(*theRealShape)->theRect, sizeof(Rect));
  560.     if (!myErr)
  561.         myErr = AEPutParamPtr(&theList, keyAELineArrow, typeEnumeration, (Ptr)&noArr, sizeof(DescType));
  562.     /* we have no dash styles, so add an empty list */
  563.     myErr = AECreateList(nil, nil, false, &emptyList);
  564.     if (!myErr)
  565.         myErr = AEPutParamDesc(&theList, keyAEDashStyle, &emptyList);
  566.     AEDisposeDesc(&emptyList);
  567.     if (!myErr)
  568.         myErr = AEPutParamPtr(&theList, keyAEStartPoint, typeQDRectangle, (Ptr)&(*theRealShape)->theRect, sizeof(Point));
  569.     if (!myErr)
  570.         myErr = AEPutParamPtr(&theList, keyAEStartPoint, typeQDRectangle, (Ptr)&(*theRealShape)->theRect.bottom, sizeof(Point));
  571.     
  572.     HUnlock((Handle)theRealShape);
  573.     /* and coerce it into what we want */
  574.     if (!myErr)
  575.         myErr = AECoerceDesc(&theList, typeGraphicLine, theValue);
  576.     AEDisposeDesc(&theList);
  577.     mAEErrorDisplay("\p\n Error creating typeGraphicLine", myErr)
  578.     return(myErr);
  579. }
  580.  
  581. /* Now some of the definitions in the AE Registry are rather broad, but they */
  582. /* really need to be.  SO you'll want little routines like this */
  583. OSErr MakeSinglePixelMap(AEDesc *thePlace, RGBColor *theColor)
  584. {
  585.     OSErr myErr = noErr;
  586.     AEDescList thePixelList, tempList;
  587.     AEDesc scratchDesc;
  588.     long copyWord = kAEQDCopy;
  589.     Rect miniRect =  {
  590.         0, 0, 1, 1
  591.     };
  592.     myErr = AECreateList(nil, nil, false, &thePixelList);
  593.     if (!myErr)
  594.         myErr = AECreateDesc(typeRGBColor, (Ptr)theColor, sizeof(RGBColor), &scratchDesc);
  595.     if (!myErr)
  596.         myErr = AEPutDesc(&thePixelList, 0, &scratchDesc);
  597.     if (!myErr)
  598.         myErr = AEDisposeDesc(&scratchDesc);
  599.     /* now create the other list */
  600.     if (!myErr)
  601.         myErr = AECreateList(nil, nil, true, &tempList);
  602.     /* add the pixels */
  603.     if (!myErr)
  604.         myErr = AEPutParamDesc(&tempList, typePixMapMinus, &thePixelList);
  605.     if (!myErr)
  606.         myErr = AEDisposeDesc(&thePixelList);
  607.     if (!myErr)
  608.         myErr = AECreateDesc(typeQDRectangle, (Ptr)&miniRect, sizeof(Rect), &scratchDesc);
  609.     /* add it */
  610.     if (!myErr)
  611.         myErr = AEPutParamDesc(&tempList, keyAEBounds, &scratchDesc);
  612.     if (!myErr)
  613.         myErr = AEDisposeDesc(&scratchDesc);
  614.     /* and the transfer mode, I'm using Copy for all of these */
  615.     if (!myErr)
  616.         myErr = AECreateDesc(typeEnumeration, (Ptr)©Word, sizeof(long), &scratchDesc);
  617.     /* add it */
  618.     if (!myErr)
  619.         myErr = AEPutParamDesc(&tempList, keyAETransferMode, &scratchDesc);
  620.     if (!myErr)
  621.         myErr = AEDisposeDesc(&scratchDesc);
  622.     /* and coerce thePlace into a typePixelMap */
  623.     if (!myErr)
  624.         myErr = AECoerceDesc(&tempList, typePixelMap, thePlace);
  625.     
  626.     /* See?  Simplicity itself */
  627.     mAEErrorDisplay("\p\n Error creating pixMap", myErr)
  628.     return(myErr);
  629. }
  630.  
  631.  
  632. #undef __AEMU__
  633.